package com.lagou.register;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.CuratorWatcher;
import org.apache.curator.framework.api.GetChildrenBuilder;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;

import java.net.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

public class ZkUtil {

    public static final String basePath = "simple_rpc";
    public static final String zkAddress = "127.0.0.1:2181";
    /**
     * 获取会话客户端
     * @return
     */
    public static CuratorFramework getZkClient(){
        RetryPolicy exponentialBackoffRetry = new ExponentialBackoffRetry(1000, 3);

        // 使用fluent编程风格
        CuratorFramework client = CuratorFrameworkFactory.builder()
                .connectString(zkAddress)
                .sessionTimeoutMs(50000)
                .connectionTimeoutMs(30000)
                .retryPolicy(exponentialBackoffRetry)
                .namespace(basePath)  // 独立的命名空间
                .build();
        client.start();
        return client;
    }

    /**
     * 服务端注册服务 (创建临时节点)
     * @param client
     * @param ip
     * @param port
     * @return
     * @throws Exception
     */
    public static String register(CuratorFramework client, String ip, int port) throws Exception {
        String address = "/" + ip + ":" + port;
        return client.create().creatingParentsIfNeeded()
                .withMode(CreateMode.EPHEMERAL).forPath(address, String.valueOf(System.currentTimeMillis()).getBytes());

    }


    /**
     * 获取服务列表
     * @param client
     * @return
     */
    public static List<String> getServiceList(CuratorFramework client) {
        List<String> children = new ArrayList<>();
        Stat stat;
        try {
            stat = new Stat();
            children = client.getChildren().storingStatIn(stat).forPath("/");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return children;
    }


    public static void setData(CuratorFramework client, InetSocketAddress server, Object data){
        String hostName = server.getHostName();
        int port = server.getPort();
        try {
            client.setData().forPath("/" + hostName + ":" + port, data.toString().getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String getLocalIpv4Address() throws SocketException {
        Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
        String siteLocalAddress = null;
        while (ifaces.hasMoreElements()) {
            NetworkInterface iface = ifaces.nextElement();
            Enumeration<InetAddress> addresses = iface.getInetAddresses();
            while (addresses.hasMoreElements()) {
                InetAddress addr = addresses.nextElement();
                String hostAddress = addr.getHostAddress();
                if (addr instanceof Inet4Address
                        && !addr.isLoopbackAddress()
                       /* && !hostAddress.startsWith("192.168")
                        && !hostAddress.startsWith("172.")
                        && !hostAddress.startsWith("169.")*/) {
                    if (addr.isSiteLocalAddress()) {
                        siteLocalAddress = hostAddress;
                    } else {
                        return hostAddress;
                    }
                }
            }
        }
        return siteLocalAddress == null ? "" : siteLocalAddress;
    }
}
